﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Routing;

namespace NeuroSpeech.WebAtoms
{
    public class StaticRoute : HttpTaskAsyncHandler, IRouteHandler
    {

        private StaticRoute()
        {
            // only one per app..

        }

        private string Prefix { get; set; }

        public static string Version { get; private set; }

        private DirectoryInfo Folder { get; set; }

        private TimeSpan MaxAge { get; set; }

        private static ConcurrentBag<StaticRoute> Current = new ConcurrentBag<StaticRoute>();

        public static void Register(
            RouteCollection routes,
            string urlPrefix,
            string staticFolder,
            string version = null,
            TimeSpan? maxAge = null)
        {
            StaticRoute sc = new StaticRoute();
            sc.Prefix = urlPrefix;
            sc.MaxAge = maxAge == null ? TimeSpan.FromDays(30) : maxAge.Value;
            sc.Folder = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/" + staticFolder));

            if (string.IsNullOrWhiteSpace(version))
            {
                version = System.Web.Configuration.WebConfigurationManager.AppSettings["Static-Content-Version"];
                if (string.IsNullOrWhiteSpace(version))
                {
                    version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
                }
            }

            Version = version;

            Current.Add(sc);

            var route = new Route(urlPrefix + "/{*name}", sc);
            route.Defaults = new RouteValueDictionary();
            route.Defaults["version"] = "1";
            routes.Add(route);
        }

        public override bool IsReusable
        {
            get
            {
                return true;
            }
        }

        public static HtmlString Url(string p)
        {
            return new HtmlString(p + "?v=" + Version);
        }

        public override async System.Threading.Tasks.Task ProcessRequestAsync(HttpContext context)
        {
            var Response = context.Response;
            Response.Cache.SetCacheability(HttpCacheability.Public);
            Response.Cache.SetMaxAge(MaxAge);
            Response.Cache.SetExpires(DateTime.Now.Add(MaxAge));

            string url = context.Request.RawUrl.Substring(1);
            url = url.Substring(this.Prefix.Length);
            int index = url.IndexOf('?');
            if (index != -1)
            {
                url = url.Substring(0, index);
            }

            var file = new FileInfo(Folder.FullName + url);
            if (!file.Exists)
            {
                throw new FileNotFoundException(file.FullName);
            }

            Response.ContentType = MimeMapping.GetMimeMapping(file.FullName);

            using (var fs = file.OpenRead())
            {
                await fs.CopyToAsync(Response.OutputStream);
            }
        }

        IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
        {
            return (IHttpHandler)this;
        }
    }
}
